@=========================================
@ NAME: 2442INIT.S
@ DESC: C start up codes
@       Configure memory, ISR ,stacks
@   Initialize C-variables
@ HISTORY:
@ 2002.02.25:kwtark: ver 0.0
@ 2002.03.20:purnnamu: Add some functions for testing STOP,Sleep mode
@ 2003.03.14:DonGo: Modified for 2442.
@ 2008.06.30:Leng Bo:Modified for T8 project.
@=========================================

#include <asm/2442addr_asm.h>
#include <config.h>

#define BIT_SELFREFRESH  (1<<22)

.section .text.init
.globl _mainCRTStartup
_mainCRTStartup:
    b    reset
    b    undefined_instruction
    b    software_interrupt
    b    prefetch_abort
    b    data_abort
    b    not_used
    b    irq
    b    fiq
    b   EnterPWDN

@Function for entering power down mode
@ 1. SDRAM should be in self-refresh mode.
@ 2. All interrupt should be maksked for SDRAM/DRAM self-refresh.
@ 3. LCD controller should be disabled for SDRAM/DRAM self-refresh.
@ 4. The I-cache may have to be turned on.
@ 5. The location of the following code may have not to be changed.

@void EnterPWDN(int CLKCON)@
EnterPWDN:
    mov r2,r0       @r2=rCLKCON
    tst r0,#0x8     @SLEEP mode?
    bne ENTER_SLEEP

ENTER_STOP:
    ldr r0,=REFRESH
    ldr r3,[r0]     @r3=rREFRESH
    mov r1, r3
    orr r1, r1, #BIT_SELFREFRESH
    str r1, [r0]        @Enable SDRAM self-refresh

    mov r1,#16          @wait until self-refresh is issued. may not be needed.
0:   subs r1,r1,#1
    bne 0b

    ldr r0,=CLKCON      @enter STOP mode.
    str r2,[r0]

    mov r1,#32
1:   subs r1,r1,#1   @1) wait until the STOP mode is in effect.
    bne 1b     @2) Or wait here until the CPU&Peripherals will be turned-off
            @   Entering SLEEP mode, only the reset by wake-up is available.

    ldr r0,=REFRESH @exit from SDRAM self refresh mode.
    str r3,[r0]

    mov pc,lr

ENTER_SLEEP:
    @NOTE.
    @1) rGSTATUS3 should have the return address after wake-up from SLEEP mode.

    ldr r0,=REFRESH
    ldr r1,[r0]     @r1=rREFRESH
    orr r1, r1, #BIT_SELFREFRESH
    str r1, [r0]        @Enable SDRAM self-refresh

    mov r1,#16          @Wait until self-refresh is issued,which may not be needed.
2:   subs r1,r1,#1
    bne 2b

    ldr r1,=MISCCR
    ldr r0,[r1]
    orr r0,r0,#(7<<17)  @Set SCLK0=0, SCLK1=0, SCKE=0.
    str r0,[r1]

    ldr r0,=CLKCON      @ Enter sleep mode
    str r2,[r0]

    b .         @CPU will die here.


WAKEUP_SLEEP:
    @Release SCLKn after wake-up from the SLEEP mode.
    ldr r1,=MISCCR
    ldr r0,[r1]
    bic r0,r0,#(7<<17)  @SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE:0->=SCKE.
    str r0,[r1]

@    @Set memory control registers
@    ldr r0,=SMRDATA
@    ldr r1,=BWSCON  @BWSCON Address
@    add r2, r0, #52 @End address of SMRDATA
@3:
@    ldr r3, [r0], #4
@    str r3, [r1], #4
@    cmp r2, r0
@    bne 3b
    ldr   r1, =0x48000000
    ldr   r2, =0x22111120
    str r2, [r1], #4

    ldr   r2, =0x700
    str r2, [r1], #4
    str r2, [r1], #4
    str r2, [r1], #4
    str r2, [r1], #4
    str r2, [r1], #4
    str r2, [r1], #4

    ldr   r2, =0x18005
    str r2, [r1], #4
    str r2, [r1], #4

    ldr   r2, =0x8c0459
    str r2, [r1], #4

    ldr   r2, =0x32
    str r2, [r1], #4

    ldr   r2, =0x30
    str r2, [r1], #4
    str r2, [r1]



    mov r1,#256
4:   subs r1,r1,#1   @1) wait until the SelfRefresh is released.
    bne 4b

    ldr r1,=GSTATUS3    @GSTATUS3 has the start address just after SLEEP wake-up
    ldr r0,[r1]

    mov pc,r0

@=======
@ ENTRY
@=======
reset:
    mrs      r0,cpsr
    bic      r0,r0,#0x1f
    orr      r0,r0,#0xd3
    msr      cpsr_cf,r0  @SVC mode, close irq & fiq

    ldr r0,=WTCON       @watch dog disable
    mov r1,#0x0
    str r1,[r0]

    ldr r0,=INTMSK
    mov r1,#0xffffffff  @all interrupt disable
    str r1,[r0]

    ldr r0,=INTSUBMSK
    ldr r1,=0x7ff       @all sub interrupt disable
    str r1,[r0]

  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    @To reduce PLL lock time, adjust the LOCKTIME register.
    ldr r0,=LOCKTIME
    mov r1,#0xffffff
    str r1,[r0]

    @PLL_ON_START
    @ Added for confirm clock divide. for 2442.
    @ Setting value F:H:Pclk = 1:3:6
    ldr r0,=CLKDIVN
    mov r1,#0x7
    @ldr    r1,=CLKDIV_VAL  = 7 @ 0=1:1:1, 1=1:1:2, 2=1:2:2, 3=1:2:4, 4=1:4:4, 0x5=1:4:8, 7=1:3:6
    str r1,[r0]

    @CLKDIV_VAL>1       @ means Fclk:Hclk is not 1:1.
    @ MMU_SetAsyncBusMode
    mrc p15,0,r0,c1,c0,0
    orr r0,r0,#0xc0000000                    @#R1_nF:OR:R1_iA
    mcr p15,0,r0,c1,c0,0
    nop
    nop

    @Configure UPLL
    ldr r0,=UPLLCON
    @ldr r1,=0x00038021
    ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)  @Fin=12MHz,Fout=48MHz
    str r1,[r0]

    nop @ Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed.
    nop
    nop
    nop
    nop
    nop
    nop

    str r1,[r0]
    @Configure MPLL
    @ Mpll = (2 * m * Fin) / (p * 2s)
    @ m = (MDIV + 8), p = (PDIV + 2), s = SDIV
    ldr r0,=MPLLCON
    @ldr r1,=0xb8022
    ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)  @Fin=12MHz, Fout=300MHz
    str r1,[r0]

    @ CP15 Control
    mov      r0,#0
    mcr      p15,0x0,r0,c7,c7,0
    mcr      p15,0x0,r0,c8,c7,0
    mrc      p15,0x0,r0,c1,c0,0
    bic      r0,r0,#0x2300
    bic      r0,r0,#0x87
    orr      r0,r0,#2 @ Fault checking enabled
    orr      r0,r0,#0x1000 @ ICache enabled
    mcr      p15,0x0,r0,c1,c0,0

    @Memory initialization
    ldr   r1, =0x48000000
    ldr   r2, =0x22111120
    str r2, [r1], #4

    ldr   r2, =0x700
    str r2, [r1], #4
    str r2, [r1], #4
    str r2, [r1], #4
    str r2, [r1], #4
    str r2, [r1], #4
    str r2, [r1], #4

    ldr   r2, =0x18005
    str r2, [r1], #4
    str r2, [r1], #4

    ldr   r2, =0x8c0459
    str r2, [r1], #4

    ldr   r2, =0x32
    str r2, [r1], #4

    ldr   r2, =0x30
    str r2, [r1], #4
    str r2, [r1]


    @Check if the boot is caused by the wake-up from SLEEP mode.
    ldr r1,=GSTATUS2
    ldr r0,[r1]
    tst r0,#0x2
    @In case of the wake-up from SLEEP mode, go to SLEEP_WAKEUP handler.
    bne WAKEUP_SLEEP

StartPointAfterSleepWakeUp:
    @Set memory control registers
@   ldr r0,=SMRDATA
@   ldr r1,=BWSCON  @BWSCON Address
@   add r2, r0, #52 @End address of SMRDATA
@
@
@0
@   ldr r3, [r0], #4
@   str r3, [r1], #4
@   cmp r2, r0
@   bne %B0


    nop
    nop
    nop

    @ Enable ICache
   mrc p15,0,r0,c1,c0,0
   orr r0,r0,#(1<<12)
   mcr p15,0,r0,c1,c0,0

    mov r1,#0
    mov r2,#0
    mov r3,#0
    mov r4,#0
    mov r5,#0
    mov r6,#0
    mov r7,#0
    mov r8,#0

    mov r9,#0x1000000   @16MB
    ldr r0,=0x30000000
5:
   stmia   r0!,{r1-r8}
   subs    r9,r9,#32
   bne 5b

    @Initialize stacks
    @bl InitStacks
    ldr sp, =0x33fffff0  @ Stack base address

@   @ Setup IRQ handler
@   ldr r0,=HandleIRQ       @This routine is needed
@   ldr r1,=IsrIRQ    @if there isn't 'subs pc,lr,#4' at 0x18, 0x1c
@   str r1,[r0]
@
@   @Copy and paste RW data/zero initialized data
@   ldr r0, =|Image$$RO$$Limit| @ Get pointer to ROM data
@   ldr r1, =|Image$$RW$$Base|  @ and RAM copy
@   ldr r3, =|Image$$ZI$$Base|
@
@   @Zero init base => top of initialised data
@   cmp r0, r1      @ Check that they are different
@   beq %F2
@1
@   cmp r1, r3      @ Copy init data
@   ldrcc   r2, [r0], #4    @--> LDRCC r2, [r0] + ADD r0, r0, #4
@   strcc   r2, [r1], #4    @--> STRCC r2, [r1] + ADD r1, r1, #4
@   bcc %B1
@2
@   ldr r1, =|Image$$ZI$$Limit| @ Top of zero init segment
@   mov r2, #0
@3
@   cmp r3, r1      @ Zero init
@   strcc   r2, [r3], #4
@   bcc %B3

@ Copy data from nand flash into SDRAM
    ldr r0, =SPL_RAM_ADDRESS
    ldr r1, =SPL_SIZE @ Number of page(2KB each)
    bl CopySplFromNand @ Copy SPL code from nand flash to RAM
    nop
    @bl .
    ldr r1, =RAMBEGIN
    mov pc, r1

CopySplFromNand:
    stmdb    sp!, {r4, r5, r6, lr}
    mov    lr, #0x4c000000
    ldr    r3, [lr, #12]
    mov    ip, #0x4e000000
    orr    r3, r3, #0x10
    mov    r2, #0x600
    str    r3, [lr, #12]
    str    r2, [ip]
    mov    r3, #0x13
    sub    r2, r2, #0x600
    str    r3, [ip, #4]
    str    r2, [ip, #32]
    ldr    r3, [ip, #4]
    bic    r3, r3, #0x2
    str    r3, [ip, #4]
    ldr    r2, [ip, #32]
    mov    r3, #0xff
    orr    r2, r2, #0x4
    str    r2, [ip, #32]
    str    r3, [ip, #8]
    mov    r5, r1
    mov    lr, r0
1316: ldr    r3, [ip, #32]
    tst    r3, #0x4
    beq    1316b  @ <_CopySplFromNand+0x58>
    ldr    r3, [ip, #4]
    mov    r4, #0x0
    orr    r3, r3, #0x2
    cmp    r4, r5
    str    r3, [ip, #4]
    ldmgeia    sp!, {r4, r5, r6, pc}
    mov    ip, #0x4e000000
    mov    r6, r4
1360: ldr    r3, [ip, #4]
    orr    r3, r3, #0x10
    str    r3, [ip, #4]
    ldr    r2, [ip, #4]
    bic    r2, r2, #0x20
    str    r2, [ip, #4]
    ldr    r3, [ip, #4]
    bic    r3, r3, #0x2
    str    r3, [ip, #4]
    ldr    r2, [ip, #32]
    mov    r3, r4, asr #8
    and    r3, r3, #0xff
    mov    r1, r4, asr #16
    orr    r2, r2, #0x4
    and    r0, r4, #0xff
    str    r2, [ip, #32]
    and    r1, r1, #0xff
    str    r6, [ip, #8]
    str    r6, [ip, #12]
    str    r6, [ip, #12]
    str    r0, [ip, #12]
    str    r3, [ip, #12]
    mov    r3, #0x30
    str    r1, [ip, #12]
    str    r3, [ip, #8]
1460: ldr    r3, [ip, #32]
    tst    r3, #0x4
    beq    1460b @ <_CopySplFromNand+0xe8>
    mov    r1, #0x4e000000
    mov    r2, #0x800
1480: ldrb    r3, [r1, #16]
    subs    r2, r2, #0x1
    strb    r3, [lr], #1
    bne    1480b @ <_CopySplFromNand+0xfc>
    ldr    r3, [r1, #4]
    orr    r3, r3, #0x20
    str    r3, [r1, #4]
    ldr    r2, [r1, #4]
    add    r4, r4, #0x1
    orr    r2, r2, #0x2
    cmp    r4, r5
    str    r2, [r1, #4]
    blt    1360b @ <_CopySplFromNand+0x84>
    ldmia    sp!, {r4, r5, r6, pc}


@ From now on, the code is executed in SDRAM
@ Not in the mapped SRAM for nand flash
RAMBEGIN:
    ldr    r1, bss_start
    ldr    r0, bss_end
    sub    r0, r0, r1
    /* r1 = start address */
    /* r0 = *number of bytes */
    mov    r2, #0
    mov    r3, #0
    mov    r4, #0
    mov    r5, #0

clear_bss:
    stmia    r1!, {r2,r3,r4,r5}
    subs    r0, r0, #16
    bne    clear_bss

    bl  _c_main    @Don't use main() because ......
    b   .


.globl undefined_instruction
undefined_instruction:
    b undefined_instruction

.globl software_interrupt
software_interrupt:
    b software_interrupt

.globl prefetch_abort
prefetch_abort:
    b prefetch_abort

.globl data_abort
data_abort:
    b data_abort

.globl not_used
not_used:
    b not_used

.globl irq
irq:
    b irq

.globl fiq
fiq:
    b fiq

@=====================================================================
@ Clock division test
@ Assemble code, because VSYNC time is very short
@=====================================================================

CLKDIV124:

    ldr     r0, = CLKDIVN
    ldr     r1, = 0x3       @ 0x3 = 1:2:4
    str     r1, [r0]
@   wait until clock is stable
    nop
    nop
    nop
    nop
    nop

    ldr     r0, = REFRESH
    ldr     r1, [r0]
    bic     r1, r1, #0xff
    bic     r1, r1, #(0x7<<8)
    orr     r1, r1, #0x470  @ REFCNT135
    str     r1, [r0]
    nop
    nop
    nop
    nop
    nop
    mov     pc, lr

CLKDIV144:
    ldr     r0, = CLKDIVN
    ldr     r1, = 0x4       @ 0x4 = 1:4:4
    str     r1, [r0]
@   wait until clock is stable
    nop
    nop
    nop
    nop
    nop

    ldr     r0, = REFRESH
    ldr     r1, [r0]
    bic     r1, r1, #0xff
    bic     r1, r1, #(0x7<<8)
    orr     r1, r1, #0x630  @ REFCNT675 - 1520
    str     r1, [r0]
    nop
    nop
    nop
    nop
    nop
    mov     pc, lr

.align 4
bss_start:    .word    ___bss_start
bss_end    :    .word    ___bss_end
